package com.one.friend.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.one.common.core.constants.CacheConstants;
import com.one.common.core.enums.ResultCode;
import com.one.common.redis.service.RedisService;
import com.one.common.security.exception.ServiceException;
import com.one.friend.domain.question.Question;
import com.one.friend.domain.user.UserSubmit;
import com.one.friend.elasticsearch.QuestionRepository;
import com.one.friend.mapper.question.QuestionMapper;
import com.one.friend.mapper.user.UserSubmitMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Component
public class QuestionCacheManager {

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private QuestionRepository questionRepository;

    @Autowired
    private RedisService redisService;

    @Autowired
    private UserSubmitMapper userSubmitMapper;

    public Long getListSize(){
        return redisService.getListSize(CacheConstants.QUESTION_LIST);
    }

    public Long getHotListSize(){
        return redisService.getListSize(CacheConstants.HOT_QUESTION_LIST);
    }


    public void refreshQuestionList(){
        //从数据库中刷新缓存,只存id即可
        List<Question> questionList = questionMapper.selectList(new LambdaQueryWrapper<Question>()
                .select(Question::getQuestionId).orderByDesc(Question::getCreateTime));
        if(CollectionUtil.isEmpty(questionList)){
            throw new ServiceException(ResultCode.FAILED_NOT_EXISTS);
        }
        List<Long> questionIdList = questionList.stream().map(Question::getQuestionId).toList();
        redisService.rightPushAll(CacheConstants.QUESTION_LIST,questionIdList);
    }

    public List<Long> refreshHotQuestionList() {
        List<Long> hotQuestionIdList = new ArrayList<>();
        hotQuestionIdList = userSubmitMapper.selectHotQuestionList();
        redisService.rightPushAll(CacheConstants.HOT_QUESTION_LIST,hotQuestionIdList);
        return hotQuestionIdList;
    }

    public Object getPreQuestionId(Long questionId) {
        //获取当前位置的索引
        Long index = redisService.indexOfForList(CacheConstants.QUESTION_LIST,questionId);
        //如果已经是第一题，给出提醒
        if(index == 0){
            throw new ServiceException(ResultCode.FAILED_FIRST_QUESTION);
        }
        return redisService.indexForList(CacheConstants.QUESTION_LIST,index - 1,Long.class);
    }

    public Object getNextQuestionId(Long questionId) {
        //获取当前位置的索引
        Long index = redisService.indexOfForList(CacheConstants.QUESTION_LIST,questionId);
        //如果已经是第一题，给出提醒
        if(Objects.equals(index, getListSize()-1)){
            throw new ServiceException(ResultCode.FAILED_LAST_QUESTION);
        }
        return redisService.indexForList(CacheConstants.QUESTION_LIST,index + 1,Long.class);
    }

    public List<Long> getHotQuestionIdList() {
        //从redis当中拿取数据
        List<Long> hotQuestionIdList = redisService.getCacheListByRange(
                CacheConstants.HOT_QUESTION_LIST, 0, getHotListSize() - 1, Long.class);
        if(CollectionUtil.isEmpty(hotQuestionIdList)){
            //redis当中没有数据，从数据库从拿取并刷新到Redis
            List<UserSubmit> list = userSubmitMapper.selectList(new LambdaQueryWrapper<UserSubmit>()
                    .select(UserSubmit::getQuestionId)
                    .groupBy(UserSubmit::getQuestionId)
                    .orderByDesc(UserSubmit::getQuestionId)
                    .last("LIMIT 5"));
            hotQuestionIdList = BeanUtil.copyToList(list, Long.class);
            redisService.rightPushAll(CacheConstants.HOT_QUESTION_LIST,hotQuestionIdList);
        }
        return hotQuestionIdList;
    }

    public List<Long> getHotList() {
        //直接从redis当中获取
        return redisService.getCacheListByRange(
                CacheConstants.HOT_QUESTION_LIST, 0, getHotListSize() - 1, Long.class);
    }

}
